package com.lyj.thread.queue;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 阻塞队列
 * ArrayBlockingQueue
 *  底层以数组的形式保存数据
 *  add(E e)：把 e 加到 BlockingQueue 里，即如果 BlockingQueue 可以容纳，则返回 true，否则报异常
 * offer(E e)：表示如果可能的话，将 e 加到 BlockingQueue 里，即如果 BlockingQueue 可以容纳，则返回 true，否则返回 false
 * put(E e)：把 e 加到 BlockingQueue 里，如果 BlockQueue 没有空间，则调用此方法的线程被阻断直到 BlockingQueue 里面有空间再继续
 * poll(time)：取走 BlockingQueue 里排在首位的对象，若不能立即取出，则可以等 time 参数规定的时间,取不到时返回 null
 * take()：取走 BlockingQueue 里排在首位的对象，若 BlockingQueue 为空，阻断进入等待状态直到 Blocking 有新的对象被加入为止
 * remainingCapacity()：剩余可用的大小。等于初始容量减去当前的 size
 * ArrayBlockingQueue 使用场景。
 *   先进先出队列（队列头的是最先进队的元素；队列尾的是最后进队的元素）
 *   有界队列（即初始化时指定的容量，就是队列最大的容量，不会出现扩容，容量满，则阻塞进队操作；容量空，则阻塞出队操作）
 *   队列不支持空元素
 */
public class ArrayBlockingQueueDemo {
    // 数组阻塞队列
    static ArrayBlockingQueue<String> queue = new ArrayBlockingQueue<>(50);

    static AtomicInteger atomicInteger = new AtomicInteger(1) ;

    public static void main(String[] args) throws InterruptedException {
        // 添加测试
//        add();

        // 测试 存，取 没有分离
        addAndGet();

    }

    /**
     * 添加元素
     */
    private static void add() {

        for (int i = 0; i < 60 ; i++) {
            final int ii = i;
            new Thread(() -> {
                try {
                    String s = String.valueOf(ii);
                    // queue.add(s);// 把 e 加到 BlockingQueue 里，即如果 BlockingQueue 可以容纳，则返回 true，否则报异常
                    boolean offer = queue.offer(s);// 表示如果可能的话，将 e 加到 BlockingQueue 里，即如果 BlockingQueue 可以容纳，则返回 true，否则返回 false
                    // queue.put(s); // 把 e 加到 BlockingQueue 里，如果 BlockQueue 没有空间，则调用此方法的线程被阻断直到 BlockingQueue 里面有空间再继续
                    System.out.println(Thread.currentThread().getName() + "  put " + offer);
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }).start();
        }
    }

    /**
     * 测试 存，取 没有分离
     */
    private static void addAndGet() {
        new Thread(() ->{
            while (queue.offer(String.valueOf(atomicInteger))){
                System.out.println(atomicInteger + " 添加成功");
                atomicInteger.getAndIncrement();
                System.out.println(atomicInteger.get() + "  atomicInteger.getAndIncrement() 执行");
            }
        }).start();

        new Thread(() ->{
            try {
                while (atomicInteger.get() >= 1){
                    String poll = queue.poll(1000l, TimeUnit.MILLISECONDS);
                    System.out.println("获取数据成功：" + poll);
                    atomicInteger.decrementAndGet();
                    System.out.println(atomicInteger.get() + "  atomicInteger.getAndIncrement() 执行");
                }
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }).start();
    }

    public void doTest() {

    }
}
